//
//  NSOperationQueue_VC.m
//  thread
//
//  Created by 关旭 on 2019/3/12.
//  Copyright © 2019 guanxu. All rights reserved.
//

#import "NSOperationQueue_VC.h"

@interface NSOperationQueue_VC ()

@end

@implementation NSOperationQueue_VC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
//    [self addOperationToQueue];
//    [self addOperationWithBlockToQueue];
    [self setMaxConcurrentOperationCount];
}
#pragma mark -----------NSOperationQueue 一共有两种队列：主队列、自定义队列。其中自定义队列同时包含了串行、并发功能。下边是主队列、自定义队列的基本创建方法和特点。
- (void)simple {
#pragma mark ---------- 主队列：添加到主队列的操作都会放到主队列执行（使用addExecutionBlock：添加的额外操作除外）
//获取主队列
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    
#pragma mark --------- 自定义队列：自动开辟子线程，包含串行和并发功能
//    自定义队列创建方法
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
}

#pragma mark ------------ 将操作加入到队列中(开启新线程，并发执行)
- (void)addOperationToQueue {
//    创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
//    创建操作
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task1) object:nil];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task2) object:nil];
    
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [op3 addExecutionBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"4---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
}
- (void)task1 {
    for (int i = 0; i < 2; i++) {
        [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
        NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
    }
}
- (void)task2 {
    for (int i = 0; i < 2; i++) {
        [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
        NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
    }
}
#pragma mark -----------使用 addOperationWithBlock: 将操作加入到操作队列中(省略创建步骤)

- (void)addOperationWithBlockToQueue {
    // 1.创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 2.使用 addOperationWithBlock: 添加操作到队列中
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
}

#pragma mark -----------NSOperationQueue 控制串行执行、并发执行(开启的线程不受控制)
/*
 最大并发操作数：maxConcurrentOperationCount
 
 maxConcurrentOperationCount 默认情况下为-1，表示不进行限制，可进行并发执行。
 maxConcurrentOperationCount 为1时，队列为串行队列。只能串行执行。
 maxConcurrentOperationCount 大于1时，队列为并发队列。操作并发执行，当然这个值不应超过系统限制，即使自己设置一个很大的值，系统也会自动调整为 min{自己设定的值，系统设定的默认最大值}。
 */
- (void)setMaxConcurrentOperationCount {
//    创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
//    设置最大并发操作数
//    queue.maxConcurrentOperationCount = 1;//串行队列
//    queue.maxConcurrentOperationCount = 2;//并发队列
//    queue.maxConcurrentOperationCount = 10;//并发队列
    
    // 3.添加操作
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"4---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
